/**
 * 
 */
package io.gitee.falllee.dao.util;

import java.net.InetAddress;
import java.net.NetworkInterface;
import java.security.NoSuchAlgorithmException;
import java.security.SecureRandom;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.UUID;
import java.util.stream.Collectors;

import org.springframework.util.StringUtils;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import io.gitee.falllee.common.util.LogUtils;
import io.gitee.falllee.common.util.SpringContextUtil;
import io.gitee.falllee.dao.config.DaoConfigContextHolder;
import io.gitee.falllee.dao.model.BaseDaoConfig;
import io.gitee.falllee.dao.model.DaoConst;
import jakarta.servlet.http.HttpServletRequest;

/**
 * @author batty
 *
 */
public class CommonUtils {

    private static final String DEFAULT_DAO_CONFIG = "defaultDaoConfig";

    private CommonUtils() {}

    private static String hostIp = "";

    /**
     * 防止SQL注入
     * 
     * @param sql
     * @return
     */
    public static String transactSQLInjection(String sql) {
        return sql.replaceAll(".*([';]+|(--)+).*", " ");
    }

    /**
     * 获取请求头参数Map
     * 
     * @return 请求头参数Map
     */
    public static Map<String, String> getHeaderParam() {
        ServletRequestAttributes sra = (ServletRequestAttributes)RequestContextHolder.getRequestAttributes();
        if (sra != null) {
            HttpServletRequest request = sra.getRequest();
            return getHeaderParam(request);
        }
        return new HashMap<>(0);
    }

    /**
     * 获取请求头参数Map
     * 
     * @param request
     *            Http请求
     * @return 请求头参数Map
     */
    public static Map<String, String> getHeaderParam(HttpServletRequest request) {
        Map<String, String> headerParamsMap = new HashMap<>(16);
        BaseDaoConfig config = getDaoConfig();
        if (config != null) {
            // 取dao配置请求头员工相关字段，多个以,隔开
            String empNo = config.getHeaderParamEmpNo();
            if (StringUtils.hasLength(empNo)) {
                for (String no : empNo.split(DaoConst.COMMA)) {
                    String key = no.trim();
                    headerParamsMap.computeIfAbsent(key, request::getHeader);
                }
            }
            // 取请求头key
            String headerParamKey = config.getHeaderParamKey();
            if (StringUtils.hasLength(headerParamKey)) {
                String[] headerParamKeyArr = DaoUtils.getFixHeaderParamKey(headerParamKey);
                for (String key : headerParamKeyArr) {
                    headerParamsMap.computeIfAbsent(key, request::getHeader);
                }
            }
        }
        return headerParamsMap;
    }
    
    /**
     * 获取请求头参数Map
     * 
     * @param config DAO配置
     * 
     * @return 请求头参数Map
     */
    public static Map<String, String> getHeaderParam(BaseDaoConfig config) {
        Map<String, String> headerParamsMap = new HashMap<>(16);
        if (config != null) {
            Map<String, String> map = config.getHeaderParamsMap();
            // 取dao配置请求头员工相关字段，多个以,隔开
            String empNo = config.getHeaderParamEmpNo();
            if (StringUtils.hasLength(empNo)) {
                for (String no : empNo.split(DaoConst.COMMA)) {
                    String key = no.trim();
                    headerParamsMap.computeIfAbsent(key, p-> getValueIgnoreCase(map, p));
                }
            }
            // 取请求头key
            String headerParamKey = config.getHeaderParamKey();
            if (StringUtils.hasLength(headerParamKey)) {
                String[] headerParamKeyArr = DaoUtils.getFixHeaderParamKey(headerParamKey);
                for (String key : headerParamKeyArr) {
                    headerParamsMap.computeIfAbsent(key, p-> getValueIgnoreCase(map, p));
                }
            }
        }
        return headerParamsMap;
    }

    public static BaseDaoConfig getDaoConfig() {
        String daoConfigName = DaoConfigContextHolder.getDaoConfig();
        if (!StringUtils.hasLength(daoConfigName)) {
            BaseDaoConfig defaultDaoConfig = SpringContextUtil.getBean(DEFAULT_DAO_CONFIG, BaseDaoConfig.class);
            daoConfigName = defaultDaoConfig.getConfigName();
        }
        return (BaseDaoConfig) SpringContextUtil.getBean(daoConfigName);
    }
    
    public static int getNum(int total, int batchSize) {
        // 循环执行次数
        int num = total / batchSize;
        // 最后一次执行数量
        int left = total % batchSize;
        if (left > 0) {
            num += 1;
        }
        return num;
    }

    /**
     * 获取批量处理集合的子集合
     * 
     * @param list
     *            集合
     * @param batchSize
     *            批量处理的大小
     * @param i
     *            批量循环当前次数(从0开始)
     * @return 批量子集合
     */
    public static <T> List<T> getSubList(List<T> list, int batchSize, int i) {
        // 总数目
        int total = list.size();
        // 循环执行次数
        int num = total / batchSize;
        // 最后一次执行数量
        int left = total % batchSize;
        if (left > 0) {
            num += 1;
        }
        int fromIndex = i * batchSize;
        int toIndex = (i + 1) * batchSize;
        if (left > 0 && i == num - 1) {
            toIndex = fromIndex + left;
        }
        if (toIndex < 0 || toIndex > total) {
            return new ArrayList<>();
        }
        return list.subList(fromIndex, toIndex).stream().collect(Collectors.toList());
    }

    /**
     * 获取IP
     * 
     * @return
     */
    public static String getHostIp() {
        if (StringUtils.hasLength(hostIp)) {
            return hostIp;
        }
        InetAddress ip = null;
        try {
            boolean bFindIP = false;
            Enumeration<NetworkInterface> netInterfaces = NetworkInterface.getNetworkInterfaces();
            if (netInterfaces == null) {
                return "";
            }
            while (netInterfaces.hasMoreElements()) {
                if (bFindIP)
                    break;
                NetworkInterface ni = netInterfaces.nextElement();
                Enumeration<InetAddress> ips = ni.getInetAddresses();
                while (ips.hasMoreElements()) {
                    ip = ips.nextElement();
                    if (!ip.isLoopbackAddress() && ip.getHostAddress().matches("(\\d{1,3}\\.){3}\\d{1,3}")) {
                        bFindIP = true;
                        break;
                    }
                }
            }
        } catch (Exception e) {
            LogUtils.logException(e);
        }
        if (null != ip) {
            hostIp = ip.getHostAddress();
        }
        return hostIp;
    }
    
    /**
     * 是否JAVA类型
     * 
     * @param object
     * @return
     */
    public static boolean isBaseType(Object object) {
        if (object == null) {
            return true;
        }
        if (object.getClass().isArray() || object instanceof Collection<?>) {
            return false;
        }
        Class<? extends Object> clazz = object.getClass();
        return clazz.getClassLoader() == null;
    }
    
    /**
     * 获取随机数
     * 
     * @param num
     * @return
     */
    public static int getRandomNumber(int num) {
        try {
            SecureRandom random = SecureRandom.getInstance("SHA1PRNG");
            return random.nextInt(num);
        } catch (NoSuchAlgorithmException e) {
            return 0;
        }
    }

    /**
     * 获取请求头用户信息
     * 
     * @param headerParamsMap
     * @return
     */
    public static String getUserId(Map<String, String> headerParamsMap) {
        BaseDaoConfig config = getDaoConfig();
        return getUserId(headerParamsMap, config);
    }

    /**
     * 获取用户ID
     * 
     * @param headerParamsMap
     * @param config
     * @return
     */
    public static String getUserId(Map<String, String> headerParamsMap, BaseDaoConfig config) {
        if (config != null) {
            String empNo = config.getHeaderParamEmpNo();
            if (!StringUtils.hasLength(empNo)) {
                return "";
            }
            for (String emp : empNo.split(DaoConst.COMMA)) {
                String val = CommonUtils.getValueIgnoreCase(headerParamsMap, emp);
                if (StringUtils.hasLength(val)) {
                    return val;
                }
            }
        }
        return "";
    }

    /**
     * 获取请求头用户信息
     * 
     * @return
     */
    public static String getUserId() {
        Map<String, String> headerParamsMap = getHeaderParam();
        return getUserId(headerParamsMap);
    }

    /**
     * 获取GUID
     * 
     * @return GUID
     */
    public static String getGuid() {
        UUID uuid = UUID.randomUUID();
        return uuid.toString();
    }
    
    /**
     * 获取map值，忽略key大小写
     * 
     * @param map
     * @param key
     * @return
     */
    public static <T> T getValueIgnoreCase(Map<String, T> map, String key) {
        if (!StringUtils.hasLength(key)) {
            return null;
        }
        if (map.containsKey(key)) {
            return map.get(key);
        }
        Iterator<Entry<String, T>> iterator = map.entrySet().iterator();
        while (iterator.hasNext()) {
            Entry<String, T> entry = iterator.next();
            if (key.equalsIgnoreCase(entry.getKey())) {
                return entry.getValue();
            }
        }
        return null;
    }
    
    /**
     * 设置map值，忽略key大小写
     * 
     * @param map
     * @param key
     */
    public static <T> void setValueIgnoreCase(Map<String, T> map, String key, T t) {
        if (!StringUtils.hasLength(key)) {
            return;
        }
        Iterator<Entry<String, T>> iterator = map.entrySet().iterator();
        while (iterator.hasNext()) {
            Entry<String, T> entry = iterator.next();
            if (key.equalsIgnoreCase(entry.getKey())) {
                entry.setValue(t);
                return;
            }
        }
    }
    
    /**
     * 判断map是否包含key，忽略key大小写
     * 
     * @param map
     * @param key
     * @return
     */
    public static <T> boolean containsKeyIgnoreCase(Map<String, T> map, String key) {
        if (!StringUtils.hasLength(key)) {
            return false;
        }
        Iterator<Entry<String, T>> iterator = map.entrySet().iterator();
        while (iterator.hasNext()) {
            Entry<String, T> entry = iterator.next();
            if (key.equalsIgnoreCase(entry.getKey())) {
                return true;
            }
        }
        return false;
    }
}
